<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS-Interpreter Documentation</title>
  <link href="demos/style.css" rel="stylesheet" type="text/css">
</head>
<body>
  <img src="logo.png" height=200 width=200 style="float: right">
  <h1>JS-Interpreter Documentation</h1>

  <p>JS-Interpreter is a sandboxed JavaScript interpreter written in JavaScript.
  It allows for execution of arbitrary JavaScript code line by line.  Execution
  is completely isolated from the main JavaScript environment.  Multiple
  instances of the JS-Interpreter allow for multi-threaded concurrent JavaScript
  without the use of Web Workers.</p>

  <p>Play with the <a href="index.html">JS-Interpreter demo</a>.</p>

  <p>Get the <a href="https://github.com/NeilFraser/JS-Interpreter">source code</a>.</p>

  <h2>Usage</h2>

  <p>Start by including the two JavaScript source files:</p>

  <pre>
    &lt;script src="acorn.js"&gt;&lt;/script&gt;
    &lt;script src="interpreter.js"&gt;&lt;/script&gt;
  </pre>

  <p>Alternatively, use the compressed bundle (70kb):</p>

  <pre>
    &lt;script src="acorn_interpreter.js"&gt;&lt;/script&gt;
  </pre>

  <p>Next, instantiate an interpreter with the JavaScript code that needs to be
  parsed:</p>

  <pre>
    var myCode = 'var a=1; for(var i=0;i&lt;4;i++){a*=i;} a;';
    var myInterpreter = new Interpreter(myCode);
  </pre>

  <p>Additional JavaScript code may be added at any time (frequently used to
  interactively call previously defined functions):</p>

  <pre>
    myInterpreter.appendCode('foo();');
  </pre>

  <p>To run the code step by step, call the <code>step</code> function
  repeatedly until it returns false:</p>

  <pre>
    function nextStep() {
      if (myInterpreter.step()) {
        window.setTimeout(nextStep, 0);
      }
    }
    nextStep();
  </pre>

  <p>Alternatively, if the code is known to be safe from infinite loops, it may
  be executed to completion by calling the <code>run</code> function once:</p>

  <pre>
    myInterpreter.run();
  </pre>

  <p>In cases where the code encounters asynchronous API calls (see below),
  <code>run</code> will return true if it is blocked and needs to be reexecuted
  at a later time.</p>

  <h2>External API</h2>

  <p>Similar to the <code>eval</code> function, the result of the last
  statement executed is available in <code>myInterpreter.value</code>:</p>

  <pre>
    var myInterpreter = new Interpreter('6 * 7');
    myInterpreter.run();
    alert(myInterpreter.value);
  </pre>

  <p>Additionally, API calls may be added to the interpreter during creation.
  Here is the addition of <code>alert()</code> and a <code>url</code>
  variable:</p>

  <pre>
    var myCode = 'alert(url);';
    var initFunc = function(interpreter, scope) {
      interpreter.setProperty(scope, 'url', String(location));

      var wrapper = function(text) {
        return alert(text);
      };
      interpreter.setProperty(scope, 'alert',
          interpreter.createNativeFunction(wrapper));
    };
    var myInterpreter = new Interpreter(myCode, initFunc);
  </pre>

  <p>See the <a href="demos/json.html">JSON demo</a> for an example of
  exchanging JSON between the browser and the interpreter.
  For more complicated examples, see the <code>initGlobalScope</code> function
  which creates APIs for Math, Array, Function, and other globals.</p>

  <p>Asynchronous API functions may wrapped so that they appear to be
  synchronous to interpreter.  For example, a <code>getXhr(url)</code> function
  that returns the contents of an XMLHttpRequest could be defined in
  <code>initFunc</code> like this:</p>

  <pre>
    var wrapper = function(href, callback) {
      var req = new XMLHttpRequest();
      req.open('GET', href, true);
      req.onreadystatechange = function() {
        if (req.readyState == 4 && req.status == 200) {
          callback(req.responseText);
        }
      };
      req.send(null);
    };
    interpreter.setProperty(scope, 'getXhr',
        interpreter.createAsyncFunction(wrapper));
  </pre>

  <p>This snippet uses <code>createAsyncFunction</code> in the same way that
  <code>createNativeFunction</code> was used earlier.  The difference is that
  the wrapped asynchronous function's return value is ignored.  Instead, an
  extra callback function is passed in when the wrapper is called.  When the
  wrapper is ready to return, it calls the callback function with the value it
  wishes to return.  From the point of view of the code running inside the
  JS-Interpreter, a function call was made and the result was returned
  immediately.</p>

  <p>For a working example, see the
  <a href="demos/async.html">async demo</a>.</p>

  <h2>Serialization</h2>

  <p>A unique feature of the JS-Interpreter is its ability to pause execution,
  serialize the current state, then resume the execution at that point at a
  later time.  Loops, variables, closures, and all other state is preserved.</p>

  <p>Uses of this feature include continuously executing programs that survive
  a server reboot, loading a stack image that has been computed up to a certain
  point, forking execution, or rolling back to a stored state.</p>

  <p>One drawback is that the serialized format is not human-readable, and it is
  also not guaranteed that future versions of the JS-Interpreter will be able to
  parse the serialization from older versions.  Another drawback is that
  serialization reaches beyond the public API, and thus does not work with the
  compressed bundle (acorn_interpreter.js).  Yet another drawback is that the
  serialization format is rather large; it has a 60 kb overhead due to the
  standard polyfills.</p>

  <p>For a working example, see the
  <a href="demos/serialize.html">serialization demo</a>.</p>

  <h2>Threading</h2>

  <p>JavaScript is single-threaded, but the JS-Interpreter allows one to run
  multiple threads at the same time.  Creating two or more completely
  independent threads that run separately from each other is trivial: just
  create two or more instances of the Interpreter, each with its own code,
  and alternate calling each interpreter's step function.  They may
  communicate indirectly with each other through any external APIs that are
  provided.</p>

  <p>A slightly more complex case is where two or more threads should share the
  same global scope.  To implement this, 1) create one JS-Interpreter, 2) create
  a separate list of stacks, 3) assign the <code>.scope</code> property of the
  root node of each stack to the interpreter's <code>.global</code> property,
  4) then assign the desired stack to the interpreter's <code>stateStack</code>
  property before calling <code>step</code>.</p>

  <p>For a working example, see the
  <a href="demos/thread.html">thread demo</a>.</p>

  <h2>Security</h2>

  <p>A common use-case of the JS-Interpreter is to sandbox potentially hostile
  code.  The interpreter is secure by default: it does not use blacklists to
  prevent dangerous actions, instead it creates its own virtual machine with no
  external APIs except as provided by the developer.  To date not one security
  bug has been reported.</p>

  <p>Infinite loops are handled by calling the <code>step</code> function
  a maximum number of times, or by calling <code>step</code> indefinitely many
  times but using a setTimeout between each call to ensure other tasks have a
  chance to execute.</p>

  <p>Memory bombs (e.g. <code>var x='X'; while(1) x=x+x;</code>) can be detected
  by periodically serializing the interpereter into a JSON string, and aborting
  execution if the string length is too long.</p>

  <h2>Regular Expressions</h2>

  <p>Pathological regular expressions can execute in geometric time.  For example
  <code>'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac'.match(/^(a+)+b/)</code>
  will effectively crash any JavaScript runtime.  JS-Interpreter has a
  variety of methods for <a href="demos/regexp.html">safely dealing with
  regular expressions</a> depending on the platform.</p>

  <h2>Limitations</h2>

  <p>The version of JavaScript implemented by the interpreter has a few
  differences from that which executes in a browser:</p>

  <dl>
    <dt>API</dt>
    <dd>None of the DOM APIs are exposed.  That's kind of the point of a
    sandbox.  If you need these, write your own interfaces.</dd>
    <dt>ES6</dt>
    <dd>More recent additions to JavaScript such as <code>let</code> or
    <code>Set</code> aren't implemented.  Feel free to fork the project if you need more than ES5.</dd>
    <dt>toString &amp; valueOf</dt>
    <dd>User-created functions are not called when casting objects to primitives.</dd>
    <dt>Performance</dt>
    <dd>The interpreter is not particularly efficient.  It currently runs about
    200 times slower than native JavaScript.</dd>
  </dl>

  <h2>Node.js</h2>

  <p>JS-Intepreter can be run server-side using Node.js.  For a minimal demo,
  just run: <code>node <a href="demos/node.js">demos/node.js</a></code></p>

  <h2>Dependency</h2>

  <p>The only dependency is <a href="http://marijnhaverbeke.nl/acorn/">Acorn</a>,
  a beautifully written JavaScript parser by Marijn Haverbeke.  It is included
  in the JS-Interpreter package.</p>

  <h2>Compatibility</h2>

  <p>The limiting factor for browser support is the use of
  <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create"><code>Object.create(null)</code></a>
  to create hash objects in both Acorn and JS-Interpreter.
  This results in the following minimum browser requirements:</p>

  <ul>
    <li>Chrome 5</li>
    <li>Firefox 4.0</li>
    <li>IE 9</li>
    <li>Edge (all versions)</li>
    <li>Opera 11.6</li>
    <li>Safari 5</li>
    <li>Node.js (all versions)</li>
  </ul>

  <p>Additionally, if safely executing regular expressions is required, then
  IE 11 is the minimum version of IE that supports Web Workers via Blobs.</p>

  <h2>Disclaimer</h2>

  <p>This project is not an official Google product.</p>
</body>
</html>
